package com.jzo2o.health.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.read.listener.PageReadListener;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jzo2o.common.expcetions.BadRequestException;
import com.jzo2o.common.expcetions.DBException;
import com.jzo2o.common.utils.BeanUtils;
import com.jzo2o.common.utils.DateUtils;
import com.jzo2o.health.mapper.ReservationSettingMapper;
import com.jzo2o.health.model.domain.ReservationData;
import com.jzo2o.health.model.domain.ReservationSetting;
import com.jzo2o.health.model.dto.request.ReservationSettingUpsertReqDTO;
import com.jzo2o.health.model.dto.response.ReservationDateResDTO;
import com.jzo2o.health.model.dto.response.ReservationSettingResDTO;
import com.jzo2o.health.service.ReservationSettingService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;


/**
 * @Description ReservationSettingServiceImpl
 * @Author dmx
 * @Date 2024-12-13
 */
@Service
public class ReservationSettingServiceImpl extends ServiceImpl<ReservationSettingMapper, ReservationSetting> implements ReservationSettingService {

    /**
     * 按月查询预约设置
     *
     * @param date
     * @return
     */
    @Override
    public List<ReservationSettingResDTO> getReservationSettingByMonthList(String date) {

        List<ReservationSetting> list = lambdaQuery()
                .likeRight(ReservationSetting::getOrderDate, date)
                .list();
        //集合为空的话返回空集合
        List<ReservationSettingResDTO> reservationSettingResDTOList = new ArrayList<>();
        if (CollectionUtil.isEmpty(list)) {
            return Collections.emptyList();
        }

        //遍历查到的集合
        for (ReservationSetting reservationSetting : list) {
            ReservationSettingResDTO reservationSettingResDTO = BeanUtils.copyBean(reservationSetting, ReservationSettingResDTO.class);
            reservationSettingResDTO.setDate(reservationSetting.getOrderDate().toString());
            reservationSettingResDTOList.add(reservationSettingResDTO);
        }
        //返回结果
        return reservationSettingResDTOList;
    }

    /**
     * 编辑预约设置
     *
     * @param dto
     */
    @Override
    public void ReservationSettingUpsertReqDTO(ReservationSettingUpsertReqDTO dto) {
        //1.根据日期查询数据库
        ReservationSetting reservationSetting = lambdaQuery()
                .eq(ReservationSetting::getOrderDate, dto.getOrderDate())
                .one();

        if (BeanUtils.isEmpty(reservationSetting)) {
            //新增
            //2.判断dto是否为空，可预约人数number>0 <1000
            if (BeanUtils.isEmpty(dto) || dto.getNumber() < 0 || dto.getNumber() > 1000) {
                throw new BadRequestException("数据不合规");
            }
            ReservationSetting reservationSetting1 = BeanUtils.copyBean(dto, ReservationSetting.class);
            //3.向表中插入数据或修改对应日期的数据
            boolean saveResult = this.save(reservationSetting1);
            //4.判断是否新增是否成功
            if (!saveResult) {
                throw new DBException("插入数据失败");
            }
        } else {
            //修改
            //3.判断填写的预约人数是否大于等于已经预约的人数
            if (dto.getNumber() < reservationSetting.getReservations()) {
                throw new BadRequestException("数据不合规");
            }
            //修改预约人数
            boolean updateResult = lambdaUpdate()
                    .set(ReservationSetting::getNumber, dto.getNumber())
                    .eq(ReservationSetting::getOrderDate, reservationSetting.getOrderDate())
                    .update();
            //判断修改是否成功
            if (!updateResult) {
                throw new BadRequestException("修改失败");
            }
        }
    }

    /**
     * 用户端按月查询可预约的日期
     *
     * @param month
     * @return
     */
    @Override
    public ReservationDateResDTO getReservationDateByMonth(String month) {
        //1.select * from reservation_setting where order_date like moth%模糊查询出结果
        List<ReservationSetting> list = lambdaQuery()
                .likeRight(ReservationSetting::getOrderDate, month)
                .list();
        if (CollectionUtil.isEmpty(list)) {
            return null;
        }
        List<String> dateList = new ArrayList<>();
        //2.处理日期
        for (ReservationSetting reservationSetting : list) {
            if (reservationSetting.getNumber() > reservationSetting.getReservations()) {
                dateList.add(reservationSetting.getOrderDate().toString());
            }
        }
        return new ReservationDateResDTO(dateList);
    }

    /**
     * 批量管理预约设置
     *
     * @param formData
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void batchSave(MultipartFile formData) {
        //1.判断文件是否为空
        if (formData.isEmpty()) {
            throw new BadRequestException("文件为空");
        }

        //List<ReservationSetting> reservationSettingsUpdate = new ArrayList<>();
        List<ReservationSetting> reservationSettingsSave = new ArrayList<>();

        try {
            //获取数据库中的时间信息
            Set<LocalDate> existingDates = getExistingOrderDates();

            List<ReservationData> reservationData = this.readExcel(formData);
            for (ReservationData reservationDatum : reservationData) {
                ReservationSetting reservationSetting = new ReservationSetting();
                reservationSetting.setOrderDate(LocalDate.parse(reservationDatum.getOrderDate()));//
                reservationSetting.setNumber(reservationDatum.getReservationCount());
                // 如果 order_date 已经存在，则使用 saveOrUpdate 方法更新记录
                if (existingDates.contains(LocalDate.parse(reservationDatum.getOrderDate()))) {
                    //reservationSettingsUpdate.add(reservationSetting);
                    LambdaUpdateWrapper<ReservationSetting> in = Wrappers.<ReservationSetting>lambdaUpdate()
                            .in(ReservationSetting::getOrderDate, existingDates)
                            .set(ReservationSetting::getNumber, reservationDatum.getReservationCount());
                    this.update(in);
                } else {
                    // 如果 order_date 不存在，则新增记录
                    reservationSettingsSave.add(reservationSetting);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
        if (CollectionUtil.isNotEmpty(reservationSettingsSave)) {
            boolean resultSave = this.saveBatch(reservationSettingsSave);
            if (!resultSave) {
                throw new DBException("操作数据库失败");
            }
        }

    }

    /**
     * easyExcel的方法
     *
     * @param file
     * @return
     * @throws Exception
     */
    private List<ReservationData> readExcel(MultipartFile file) throws Exception {
        return EasyExcel.read(file.getInputStream(), ReservationData.class, new PageReadListener<>(dataList -> {
            // 处理读取的数据
            for (Object data : dataList) {
                System.out.println(data);
            }
        })).sheet().doReadSync();
    }

    // 获取数据库中已有的 order_date
    private Set<LocalDate> getExistingOrderDates() {
        return baseMapper.selectList(null).stream()
                .map(ReservationSetting::getOrderDate)
                .collect(Collectors.toSet());
    }
}
